home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 1.iso / games / yalife.zip / SOURCE / LIFE.CPP < prev    next >
C/C++ Source or Header  |  1993-09-08  |  13KB  |  425 lines

  1. // (c) Jean MICHEL June 1993 -- any modifications must be signaled to the
  2. // author
  3.  
  4. // Class TLifeWindow is for the main program window
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <owl.h>
  9. #include <commdlg.h>
  10. #include <dir.h>
  11. #include <io.h>
  12. #include <string.h>
  13. #include <filedial.h>
  14. #include <static.h>
  15. #include "efns.h"
  16. #include "cell.h"
  17. #include "shapewnd.h"
  18. #include "life.h"
  19. HPEN Pens[3]; HBRUSH Brushes[3];
  20. COLORREF Colors[3];
  21.  
  22. class TLife : public TApplication
  23. {
  24. public:
  25.   TLife(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance,
  26.     LPSTR lpCmdLine, int nCmdShow)
  27.     : TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {};
  28.   virtual void InitMainWindow();
  29. };
  30.  
  31. _CLASSDEF(TLifeWindow)
  32. class TLifeWindow : public TWindow
  33. {
  34. public:
  35.   cellpop v;
  36.   cell_type box_start,box_end;
  37.   BOOL drawing;
  38.   HDC DrawDC;
  39.   int magnification;
  40.   RECT ScrollRange;
  41.   long gencounter;
  42.   struct {long x;long y;}origin;// Logical coordinates of top left
  43.   void setorigin();
  44.   void info();
  45.   void DrawBox();
  46.   void Run(long count);
  47.   cell_type coordtocell(TMessage::tagLP);
  48.   int update(cellpop& w);
  49.   void pixel(HDC DC,cell_type c,int color);
  50.   char *GetFileName();
  51.   TLifeWindow(PTWindowsObject AParent, LPSTR ATitle);
  52.   ~TLifeWindow();
  53.   void adjustscroll(int newmag);
  54.   virtual void SetupWindow();
  55.   virtual void Paint(HDC DC, PAINTSTRUCT& PS);
  56.   virtual void WMLButtonDown(RTMessage Msg)
  57.     = [WM_FIRST + WM_LBUTTONDOWN];
  58.   virtual void WMRButtonDown(RTMessage Msg)
  59.     = [WM_FIRST + WM_RBUTTONDOWN];
  60.   virtual void WMRButtonUp(RTMessage Msg)
  61.     = [WM_FIRST + WM_RBUTTONUP];
  62.   virtual void WMMouseMove(RTMessage Msg)
  63.     = [WM_FIRST + WM_MOUSEMOVE];
  64.   virtual void CMShape(RTMessage Msg)
  65.     = [CM_FIRST + CM_SHAPE];
  66.   virtual void CMUFileSave(RTMessage Msg)
  67.     = [CM_FIRST + CM_U_FILESAVEAS];
  68.   virtual void CMUFileSaveArea(RTMessage Msg)
  69.     = [CM_FIRST + CM_U_FILESAVEAREAAS];
  70.   virtual void CMErase(RTMessage Msg)
  71.     = [CM_FIRST + CM_ERASE];
  72.   virtual void CMColorSet(RTMessage Msg)
  73.     = [CM_FIRST + CM_COLOR_SET];
  74.   virtual void CMColorReset(RTMessage Msg)
  75.     = [CM_FIRST + CM_COLOR_RESET];
  76.   virtual void CMColorUnset(RTMessage Msg)
  77.     = [CM_FIRST + CM_COLOR_UNSET];
  78.   virtual void CMClearGen(RTMessage Msg)
  79.     = [CM_FIRST + CM_CLEAR_GEN];
  80.   void CMUColor(int index);
  81.   virtual void CMFileNew(RTMessage Msg)
  82.     = [CM_FIRST + CM_FILENEW];
  83.   virtual void CMHelp(RTMessage Msg)
  84.     = [CM_FIRST + CM_HELP];
  85.   virtual void CMHelphelp(RTMessage Msg)
  86.     = [CM_FIRST + CM_HELPHELP];
  87.   virtual void CMAbout(RTMessage Msg)
  88.     = [CM_FIRST + CM_ABOUT];
  89.   virtual void CMZoomOut(RTMessage Msg)
  90.     = [CM_FIRST + CM_ZOOMOUT];
  91.   virtual void CMZoomIn(RTMessage Msg)
  92.     = [CM_FIRST + CM_ZOOMIN];
  93.   virtual void CMStep(RTMessage Msg)
  94.     = [CM_FIRST + CM_STEP];
  95.   virtual void CMRun(RTMessage Msg)
  96.     = [CM_FIRST + CM_RUN];
  97. };
  98.  
  99. int mags[]={1,2,3,5,7,10,15,25};int magindex=4;
  100.  
  101. TLifeWindow::TLifeWindow(PTWindowsObject AParent, LPSTR ATitle)
  102.   : TWindow(AParent, ATitle)
  103. { AssignMenu("COMMANDS");
  104.   Attr.Style|= WS_VSCROLL|WS_HSCROLL;
  105.   magnification=mags[magindex];origin.x=origin.y=0;
  106.   drawing=FALSE;
  107.   Scroller=new TScroller(this,1,1,1,1); // meaningless values -- setup by SetupWindow
  108.   selected_shape=cellpop("o\n");
  109.   v=cellpop();gencounter=0;
  110.   Colors[UNSET]=RGB(120,255,120);
  111.   Colors[SET]=RGB(255,0,0);
  112.   Colors[RESET]=RGB(200,0,0);
  113.   for(int i=0;i<3;i++)
  114.   { Brushes[i]=CreateSolidBrush(Colors[i]);
  115.     Pens[i]=CreatePen(PS_SOLID,1,Colors[i]);
  116.   }
  117. }
  118.  
  119. void TLifeWindow::SetupWindow()
  120. { TWindow::SetupWindow();
  121.   RECT r;GetClientRect(HWindow,&r);
  122.   ScrollRange.left=-(r.right-r.left)/(2*magnification);
  123.   ScrollRange.top=-(r.bottom-r.top)/(2*magnification);
  124.   ScrollRange.right=ScrollRange.left+1;
  125.   ScrollRange.bottom=ScrollRange.top+1;
  126.   Scroller->AutoOrg=FALSE;
  127.   adjustscroll(magnification);
  128.   readshapelib("life.lib");
  129. }
  130.  
  131. TLifeWindow::~TLifeWindow()
  132. { for(int i=0;i<3;i++)
  133.   { DeleteObject(Brushes[i]);
  134.     DeleteObject(Pens[i]);
  135.   }
  136. }
  137.  
  138. void TLifeWindow::Paint(HDC DC, PAINTSTRUCT&)
  139. { setorigin();
  140.   for(int i=0;i<v.pop;i++)pixel(DC,v.v[i],RESET);
  141.   info();
  142. }
  143.  
  144. void TLifeWindow::info()
  145. { RECT r;GetClientRect(HWindow,&r);
  146.   char text[130];
  147.   sprintf(text,
  148. "Life  Pop:%5d Gen:%5ld Mag:%d X:[%ld,%ld] Y:[%ld,%ld]",
  149.     v.pop,gencounter,magnification,
  150.     Scroller->XPos+ScrollRange.left,Scroller->XPos+ScrollRange.left+(r.right-r.left)/magnification,
  151.     Scroller->YPos+ScrollRange.top,Scroller->YPos+ScrollRange.top+(r.bottom-r.top)/magnification);
  152.   SetCaption(text);
  153. }
  154.  
  155. int TLifeWindow::update(cellpop& w)
  156. { int iw=0,iv=0,nbchg=0;
  157.   DrawDC = GetDC(HWindow);
  158.   setorigin();
  159.   while(iw!=w.pop || iv!=v.pop)
  160.   { if (w.v[iw]<v.v[iv]){ pixel(DrawDC,w.v[iw],SET);nbchg++;iw++;}
  161.     else if(w.v[iw]==v.v[iv]){ pixel(DrawDC,w.v[iw],RESET);iw++;iv++;}
  162.     else { pixel(DrawDC,v.v[iv],UNSET);nbchg++;iv++;}
  163.   }
  164.   ReleaseDC(HWindow, DrawDC);
  165.   v=w;info();
  166.   return nbchg;
  167. }
  168.  
  169. void TLifeWindow::setorigin()
  170. { origin.x=Scroller->XPos+ScrollRange.left;
  171.   origin.y=Scroller->YPos+ScrollRange.top;
  172. }
  173.  
  174. void TLifeWindow::pixel(HDC DC,cell_type c,int color)
  175. { int border=magnification>3,x,y;
  176.   SelectObject(DC,Pens[color]);
  177.   SelectObject(DC,Brushes[color]);
  178.   x=magnification*(c.cellx()-origin.x);
  179.   y=magnification*(c.celly()-origin.y);
  180.   if(magnification>1)
  181.   Rectangle(DC,x,y,x+magnification-border,y+magnification-border);
  182.   else SetPixel(DC,x,y,Colors[color]);
  183.  
  184. cell_type TLifeWindow::coordtocell(TMessage::tagLP LP)
  185. { return cell_type(LP.Lo/magnification+origin.x,LP.Hi/magnification+origin.y);}
  186.  
  187. void TLifeWindow::WMLButtonDown(RTMessage Msg)
  188. { cellpop w=v;
  189.   w.add(w,selected_shape,coordtocell(Msg.LP),LAY_XOR);
  190.   if(selected_shape.pop!=1)selected_shape="o";
  191.   update(w);
  192. }
  193.  
  194. void TLifeWindow::DrawBox()
  195. { int x1=magnification*(box_start.cellx()-origin.x);
  196.   int y1=magnification*(box_start.celly()-origin.y);
  197.   int x2=magnification*(box_end.cellx()-origin.x);
  198.   int y2=magnification*(box_end.celly()-origin.y);
  199.   DrawDC=GetDC(HWindow);
  200.   SetROP2(DrawDC,R2_NOT);
  201.   MoveTo(DrawDC,x1,y1);
  202.   LineTo(DrawDC,x1,y2);
  203.   LineTo(DrawDC,x2,y2);
  204.   LineTo(DrawDC,x2,y1);
  205.   LineTo(DrawDC,x1,y1);
  206.   ReleaseDC(HWindow,DrawDC);
  207. }
  208.  
  209. void TLifeWindow::WMRButtonDown(RTMessage Msg)
  210. { drawing=TRUE;SetCapture(HWindow);
  211.   DrawBox();box_start=box_end=coordtocell(Msg.LP);DrawBox();
  212. }
  213.  
  214. void TLifeWindow::WMMouseMove(RTMessage Msg)
  215. { if(drawing)
  216.   { DrawBox(); box_end=coordtocell(Msg.LP);DrawBox();}
  217. #if 0
  218.   setorigin();
  219.   char buf[20]; sprintf(buf,"%04ld,%04ld",origin.x,origin.y);
  220.   DrawDC = GetDC(HWindow);
  221.   TextOut(DrawDC,10,10,buf,strlen(buf));
  222.   ReleaseDC(HWindow,DrawDC);
  223. #endif
  224. }
  225.  
  226. void TLifeWindow::WMRButtonUp(RTMessage Msg)
  227. { drawing=FALSE;
  228.   ReleaseCapture();
  229. }
  230.  
  231. void TLifeWindow::Run(long count)
  232. { MSG msg;//PeekMessage(&msg,NULL,0,0,PM_REMOVE);
  233.   cellpop w,res;res.pop=-1;
  234.   do
  235.   {  w.nextgen(v);
  236.      if(w.error())return;
  237.      if(w==v){efns(WARNING_,"stable");return;}
  238.      if(w==res){efns(WARNING_,"period 2");return;}
  239.      gencounter++;res=v;
  240.      update(w);
  241.      if(w.pop==0){efns(WARNING_,"dead");return;}
  242.      if( PeekMessage(&msg,NULL,0x00A1,0x0209,PM_REMOVE))
  243.      {  TranslateMessage(&msg);
  244.         DispatchMessage(&msg);
  245.     if((msg.message<=0xA9 || msg.message>=0x106)
  246.            && (msg.message<=0x108 || msg.message>=0x201))
  247.         break;
  248.      }
  249.   }
  250.   while(--count>0);
  251. }
  252.  
  253. void TLifeWindow::CMStep(RTMessage m){Run(1);}
  254.  
  255. void TLifeWindow::CMRun(RTMessage m){Run(10000);}
  256.  
  257. void TLifeWindow::adjustscroll(int newmag)
  258. { RECT r;GetClientRect(HWindow,&r);
  259.   Scroller->XPos+=(newmag-magnification)*(r.right-r.left)/(2*newmag*magnification);
  260.   Scroller->YPos+=(newmag-magnification)*(r.bottom-r.top)/(2*newmag*magnification);
  261.   magnification=newmag;
  262.   Scroller->XLine=Scroller->YLine=25/magnification;
  263.   Scroller->SetUnits(magnification,magnification);
  264.   RECT NewRange;
  265.   if(v.pop>0)
  266.   { NewRange.left=v.firstx().cellx();
  267.     NewRange.right=v.lastx().cellx();
  268.     NewRange.top=v.firsty().celly();
  269.     NewRange.bottom=v.lasty().celly();
  270.   }
  271.   else
  272.   { NewRange.left=0;
  273.     NewRange.right=0;
  274.     NewRange.top=0;
  275.     NewRange.bottom=0;
  276.   }
  277.   NewRange.left-=(r.right-r.left)/magnification;
  278.   NewRange.top-=(r.bottom-r.top)/magnification;
  279.   Scroller->XPos+=ScrollRange.left-NewRange.left;
  280.   Scroller->YPos+=ScrollRange.top-NewRange.top;
  281.   ScrollRange=NewRange;
  282.   Scroller->SetRange(ScrollRange.right-ScrollRange.left,ScrollRange.bottom-ScrollRange.top);
  283.   InvalidateRect(HWindow, NULL, TRUE);
  284. }
  285.  
  286. void TLifeWindow::CMZoomIn(RTMessage)
  287. { if(magnification==25)return;
  288.   adjustscroll(mags[++magindex]);
  289. }
  290.  
  291. void TLifeWindow::CMZoomOut(RTMessage)
  292. { if(magnification==1)return;
  293.   adjustscroll(mags[--magindex]);
  294. }
  295.  
  296. void TLifeWindow::CMFileNew(RTMessage)
  297. { v.clear_pop();gencounter=0;
  298.   InvalidateRect(HWindow, NULL, TRUE);}
  299.  
  300. void TLifeWindow::CMErase(RTMessage)
  301. { cellpop w=v;
  302.   w.erase_rect(box_start,box_end);update(w);
  303.   DrawBox();box_end=box_start;
  304. }
  305.  
  306. char *TLifeWindow::GetFileName()
  307. { OPENFILENAME ofnTemp;
  308.   static char FileName[MAXPATH];
  309.   char szTemp[] = "All Files (*.*)\0*.*\0Life Files (*.lfe)\0*.lfe\0";
  310. /*
  311. Some Windows structures require the size of themselves in an effort to
  312. provide backward compatibility with future versions of Windows.  If the
  313. lStructSize member is not set the call to GetOpenFileName() will fail.
  314. */
  315.   ofnTemp.lStructSize = sizeof( OPENFILENAME );
  316.   ofnTemp.hwndOwner = HWindow;        // An invalid hWnd causes non-modality
  317.   ofnTemp.hInstance = 0;
  318.   ofnTemp.lpstrFilter = (LPSTR)szTemp;    // See previous note concerning string
  319.   ofnTemp.lpstrCustomFilter = NULL;
  320.   ofnTemp.nMaxCustFilter = 0;
  321.   ofnTemp.nFilterIndex = 2;
  322.   FileName[0]='\0';
  323.   ofnTemp.lpstrFile = FileName;    // Stores the result in this variable
  324.   ofnTemp.nMaxFile = sizeof( FileName );
  325.   ofnTemp.lpstrFileTitle = NULL;
  326.   ofnTemp.nMaxFileTitle = 0;
  327.   ofnTemp.lpstrInitialDir = NULL;
  328.   ofnTemp.lpstrTitle = "Save Area";                // Title for dialog
  329.   ofnTemp.Flags = OFN_HIDEREADONLY | OFN_NOREADONLYRETURN|OFN_OVERWRITEPROMPT;
  330.   ofnTemp.nFileOffset = 0;
  331.   ofnTemp.nFileExtension = 0;
  332.   ofnTemp.lpstrDefExt = "lfe";
  333.   ofnTemp.lCustData = NULL;
  334.   ofnTemp.lpfnHook = NULL;
  335.   ofnTemp.lpTemplateName = NULL;
  336. /*
  337. If the call to GetOpenFileName() fails you can call CommDlgExtendedError()
  338. to retrieve the type of error that occured.
  339. */
  340.   if(GetSaveFileName( &ofnTemp ) != TRUE)
  341.   { DWORD Errval=CommDlgExtendedError();
  342.     if(Errval!=0)   // 0 value means user selected Cancel
  343.       efns(WARNING_,"GetSaveFileName returned Error #%ld",Errval);
  344.   }
  345.   return FileName;
  346. }
  347.  
  348. void TLifeWindow::CMUFileSave( RTMessage )
  349. {v.save(GetFileName());}
  350.  
  351. void TLifeWindow::CMUFileSaveArea( RTMessage )
  352. { DrawBox();
  353.   v.save_rect(GetFileName(),box_start,box_end);
  354.   box_end=box_start;
  355. }
  356.  
  357. void TLifeWindow::CMColorUnset(RTMessage Msg){CMUColor(UNSET);}
  358. void TLifeWindow::CMColorReset(RTMessage Msg){CMUColor(RESET);}
  359. void TLifeWindow::CMColorSet(RTMessage Msg){CMUColor(SET);}
  360. void TLifeWindow::CMClearGen(RTMessage Msg){gencounter=0;info();}
  361.  
  362.  
  363. void TLifeWindow::CMUColor(int index)
  364. { CHOOSECOLOR ccTemp;
  365.   COLORREF crTemp[16];    // Important, sometimes unused, array
  366.  
  367.   ccTemp.lStructSize = sizeof( CHOOSECOLOR );
  368.   ccTemp.hwndOwner = HWindow;
  369.   ccTemp.hInstance = 0;
  370.   ccTemp.rgbResult = Colors[index]; // CC_RGBINIT flag makes this the default color
  371. /*
  372. lpCustColors must be set to a valid array of 16 COLORREF's, even if it
  373. is not used.  If it isn't you will probably fail with a GP fault in
  374. COMMDLG.DLL.
  375. */
  376.   ccTemp.lpCustColors=crTemp;
  377.   ccTemp.Flags= CC_RGBINIT;
  378.   ccTemp.lCustData=0L;
  379.   ccTemp.lpfnHook=NULL;
  380.   ccTemp.lpTemplateName=NULL;
  381.   if(ChooseColor(&ccTemp)==TRUE)
  382.   { Colors[index]=ccTemp.rgbResult;
  383.     DeleteObject(Brushes[index]);
  384.     DeleteObject(Pens[index]);
  385.     Brushes[index]=CreateSolidBrush(Colors[index]);
  386.     Pens[index]=CreatePen(PS_SOLID,1,Colors[index]);
  387.     InvalidateRect( HWindow, NULL, TRUE );
  388.   }
  389. }
  390.  
  391. void TLifeWindow::CMHelp(RTMessage)
  392. { WinHelp(HWindow,"LIFE.HLP",HELP_CONTENTS,0l);}
  393.  
  394. void TLifeWindow::CMHelphelp(RTMessage)
  395. { WinHelp(HWindow,NULL,HELP_HELPONHELP,0l);}
  396.  
  397. void TLifeWindow::CMAbout(RTMessage Msg)
  398. { MessageBox(HWindow,"Windows Life\n\n"
  399.                      "Version 0.1 June 1993\n\n"
  400.              "(C) Jean MICHEL\n\n"
  401.              " 22, rue de Wattignies 75012 Paris France\n"
  402.              " E-Mail: michel@dmi.ens.fr","About Life",MB_OK);}
  403.  
  404. void TLifeWindow::CMShape(RTMessage)
  405. { PTWindow ShapeWindow;
  406.   ShapeWindow = new TShapeWindow(this);
  407.   GetApplication()->MakeWindow(ShapeWindow);
  408. }
  409.  
  410. void TLife::InitMainWindow()
  411. { MainWindow = new TLifeWindow(NULL, Name);
  412. }
  413.  
  414. #include "winerror.h"
  415. void (cdecl *efns)(int errcode,char *fmt,...)=error;
  416.  
  417. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  418.   LPSTR lpCmdLine, int nCmdShow)
  419. { TLife Life("Windows Life (C) Jean MICHEL Version 0.0", hInstance, hPrevInstance,
  420.            lpCmdLine, nCmdShow);
  421.   Life.Run();
  422.   return Life.Status;
  423. }
  424.